﻿using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using System.Collections.Generic;
using UnityEngine;

namespace IQIGame.Onigao.Game
{
    public class UIChildeNodeHelper
    {
        private readonly UIBaseWindow belongWindow;
        private readonly UIBaseNode belongNode;
        private List<UIBaseNode> childList = new(8);
        private Dictionary<string, UIBaseNode> dicAssetPath2ChildNode = new(8);

        private bool isUpdate => this.belongNode.isUpdate;
        private bool isLateUpdate => this.belongNode.isLateUpdate;
        private ResLoader resLoader => this.belongWindow.resLoader;

        public UIChildeNodeHelper(UIBaseWindow belongWindow, UIBaseNode belongNode)
        {
            this.belongWindow = belongWindow;
            this.belongNode = belongNode;
        }

        public T InitNode<T>(GameObject node) where T : UIBaseNode, new()
        {
            return this.NewNode<T>(node);
        }

        private T NewNode<T>(GameObject node) where T : UIBaseNode, new()
        {
            T ret = new();
            ret.Init(node, this.belongWindow, this.belongNode);
            ret.isUpdate = this.isUpdate;
            ret.isLateUpdate = this.isLateUpdate;
            ret.Hide();// 默认创建的对象是隐藏的(需要外部调用显示逻辑)
            this.AddNode(ret);
            return ret;
        }

        private void AddNode<T>(T obj) where T : UIBaseNode, new()
        {
            this.childList.Add(obj);
        }

        public async UniTask<T> InitNodeAsync<T>(string nodeAssetPath, Transform nodeParent = null) where T : UIBaseNode, new()
        {
            this.belongWindow.SetInternalUICover(true);
            if (!this.dicAssetPath2ChildNode.TryGetValue(nodeAssetPath, out var node))
            {
                var prefab = await this.resLoader.LoadABAssetAwait<GameObject>(nodeAssetPath);
                var gobj = GameObject.Instantiate(prefab, nodeParent ?? this.belongNode.transform);
                gobj.ResetRectTransform();
                node = this.NewNode<T>(gobj);
                this.dicAssetPath2ChildNode.Add(nodeAssetPath, node);
            }
            this.belongWindow.SetInternalUICover(false);
            return (T)node;
        }

        public void LateUpdate()
        {
            for (int i = childList.Count - 1; i >= 0; i--)
            {
                var node = childList[i];
                if (node.isLateUpdate)
                    node.LateUpdate();
            }
        }

        public void Update(float dt, float unscaledDt)
        {
            for (int i = childList.Count - 1; i >= 0; i--)
            {
                var node = childList[i];
                if (node.isUpdate)
                    node.Update(dt, unscaledDt);
            }
        }

        public void Clear()
        {
            this.dicAssetPath2ChildNode.Clear();
            this.ClearNode();
        }

        private void ClearNode()
        {
            for (int i = this.childList.Count - 1; i >= 0; i--)
            {
                var node = this.childList[i];
                node.Dispose();
            }
        }
    }
}
